from ..log import log_gui
class BadPositionSpec(Exception): pass

class DynamicPosition:
  def __init__(self, item, left_of=None, right_of=None, above=None, below=None,
      hcenter=None, vcenter=None, hspacing=(0, 0), vspacing=(0, 0), left_at=None,
      right_at=None, top_at=None, bottom_at=None):
    self.item = item
    self.left_of = left_of
    self.right_of = right_of
    self.above = above
    self.below = below
    self.hcenter = hcenter
    self.vcenter = vcenter
    self.left_spacing = hspacing[0]
    self.right_spacing = hspacing[1]
    self.top_spacing = vspacing[0]
    self.bottom_spacing = vspacing[1]
    self.left_at = left_at
    self.right_at = right_at
    self.top_at = top_at
    self.bottom_at = bottom_at

  def __str__(self):
    return "<DynamicPosition item=%s left_of=%s right_of=%s above=%s below=%s hcenter=%s vcenter=%s left_spacing=%s right_spacing=%s top_spacing=%s bottom_spacing=%s left_at=%s right_at=%s top_at=%s bottom_at=%s>" % (
        self.item,
        self.left_of,
        self.right_of,
        self.above,
        self.below,
        self.hcenter,
        self.vcenter,
        self.left_spacing,
        self.right_spacing,
        self.top_spacing,
        self.bottom_spacing,
        self.left_at,
        self.right_at,
        self.top_at,
        self.bottom_at)

  def GetItem(self):
    return self.item

  def GetLeft(self):
    if self.left_of:
      return self.left_of.GetLeft() - self.GetWidth()

    if self.right_of:
      return self.right_of.GetLeft() + self.right_of.GetWidth()

    if self.hcenter:
      return self.hcenter.GetLeft() + (
          self.hcenter.GetWidth() - self.GetWidth()) / 2

    if self.left_at:
      return self.left_at.GetLeft()

    if self.right_at:
      return self.rigth_at.GetRight()

    raise BadPositionSpec()

  def GetTop(self):
    if self.above:
      return self.above.GetTop() - self.GetHeight()

    if self.below:
      return self.below.GetTop() + self.below.GetHeight()

    if self.vcenter:
      return self.vcenter.GetTop() + (
          self.vcenter.GetHeight() - self.GetHeight()) / 2

    if self.top_at:
      return self.top_at.GetTop()

    if self.bottom_at:
      return self.bottom_at.GetBottom()

    raise BadPositionSpec()

  def GetInnerTop(self):
    # Get the position where drawing should begin (leaving empty room for
    # spacing)
    return self.GetTop() + self.top_spacing

  def GetInnerLeft(self):
    # Get the position where drawing should begin (leaving empty room for
    # spacing)
    return self.GetLeft() + self.left_spacing

  def GetWidth(self):
    return self.item.GetWidth() + self.left_spacing + self.right_spacing

  def GetHeight(self):
    return self.item.GetHeight() + self.top_spacing + self.bottom_spacing

  def HasUnresolvedDependencies(self):
    log_gui("Enter call to HasUnresolvedDependencies")
    for dep in (self.left_of, self.right_of, self.above, self.below,
        self.hcenter, self.vcenter, self.left_at, self.right_at, self.top_at,
        self.bottom_at):
      if dep:
        if dep.HasUnresolvedDependencies():
          log_gui("HasUnresolvedDependencies: dep=",dep,"result=True")
          return True
        log_gui("HasUnresolvedDependencies: dep=",dep,"result=False")
    return False

class VerticalSpan(DynamicPosition):
  def __init__(self, y, height):
    DynamicPosition.__init__(self, None)
    self.y = y
    self.height = height

  def __str__(self):
    return "<VerticalSpan y=%s height=%s>" % (self.y, self.height)

  def GetLeft(self):
    raise BadPositionSpec()

  def GetTop(self):
    return self.y

  def GetWidth(self):
    raise BadPositionSpec()

  def GetHeight(self):
    raise self.height

  def HasUnresolvedDependencies(self):
    return False

class HorizontalSpan(DynamicPosition):
  def __init__(self, x, width):
    DynamicPosition.__init__(self, None)
    self.x = x
    self.width = width

  def __str__(self):
    return "<HorizontalSpan x=%s width=%s>" % (self.x, self.width)

  def GetLeft(self):
    return self.x

  def GetTop(self):
    raise BadPositionSpec()

  def GetWidth(self):
    raise self.width

  def GetHeight(self):
    raise BadPositionSpec()

  def HasUnresolvedDependencies(self):
    return False

class ScreenWidth(HorizontalSpan):
  def __init__(self):
    HorizontalSpan.__init__(self, 0, 800)

  def __str__(self):
    return "<ScreenWidth>"

  def HasUnresolvedDependencies(self):
    return False

class ScreenHeight(VerticalSpan):
  def __init__(self):
    VerticalSpan.__init__(self, 0, 480)

  def __str__(self):
    return "<ScreenHeight>"

  def HasUnresolvedDependencies(self):
    return False

class FormHeight(VerticalSpan):
  def __init__(self, layout):
    VerticalSpan.__init__(self, None, None)
    self.layout = layout

  def __str__(self):
    return "<FormHeight>"

  def GetTop(self):
    return 0

  def GetHeight(self):
    return self.layout.GetHeight()

  def HasUnresolvedDependencies(self):
    return not self.layout.CanComputeHeight()

class FormWidth(HorizontalSpan):
  def __init__(self, layout):
    HorizontalSpan.__init__(self, None, None)
    self.layout = layout

  def __str__(self):
    return "<FormWidth>"

  def GetLeft(self):
    return 0

  def GetWidth(self):
    return self.layout.GetWidth()

  def HasUnresolvedDependencies(self):
    return self.layout.CanComputeWidth()

class ScreenEdge(DynamicPosition):
  def __init__(self, x=None, y=None):
    DynamicPosition.__init__(self, None)
    self.x = x
    self.y = y

  def __str__(self):
    return "<ScreenEdge x=%s y=%s>" % (self.x, self.y)

  def GetLeft(self):
    if self.x is None:
      raise BadPositionSpec()
    return self.x

  def GetTop(self):
    if self.y is None:
      raise BadPositionSpec()
    return self.y

  def GetWidth(self):
    return 0

  def GetHeight(self):
    return 0

  def HasUnresolvedDependencies(self):
    return False

class LeftScreenEdge(ScreenEdge):
  def __init__(self):
    ScreenEdge.__init__(self, x=0)

class RightScreenEdge(ScreenEdge):
  def __init__(self):
    ScreenEdge.__init__(self, x=800)

class TopScreenEdge(ScreenEdge):
  def __init__(self):
    ScreenEdge.__init__(self, y=0)

class BottomScreenEdge(ScreenEdge):
  def __init__(self):
    ScreenEdge.__init__(self, y=480)

class HBox(DynamicPosition):
  def __init__(self, **args):
    DynamicPosition.__init__(self, None, **args)
    self._children = []

  def AddChild(self, child):
    self._children.append(child)

  def GetWidth(self):
    children_width = 0
    for child in self._children:
      children_width += child.GetWidth()
    return children_width + self.left_spacing + self.right_spacing

  def GetHeight(self):
    children_height = max(0,
        *map(lambda child: child.GetHeight(), self._children))
    return children_height + self.top_spacing + self.bottom_spacing

  def HasUnresolvedDependencies(self):
    return DynamicPosition.HasUnresolvedDependencies(self) or any(
        map(lambda child: child.HasUnresolvedDependencies(), self._children))
